package club.justwill.single.Service.impl;

import club.justwill.single.Service.OrderService;
import club.justwill.single.assembler.OrderAssemble;
import club.justwill.single.bean.*;
import club.justwill.single.impl.ToolsImpl;
import club.justwill.single.model.*;
import club.justwill.single.persistence.dao.*;
import club.justwill.single.persistence.document.ProjectSupport;
import club.justwill.single.persistence.document.SupportUser;
import club.justwill.single.persistence.document.UserSupportProject;
import club.justwill.single.persistence.jpo.*;
import club.justwill.single.persistence.store.ProjectSupportStore;
import club.justwill.single.persistence.store.UserSupportProjectStore;
import club.justwill.single.util.JsonResponseHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * Created by jaylon on 15-12-26.
 */
@Service
@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
public class OrderServiceImpl extends BaseService implements OrderService {

    @Autowired
    private OrderDao orderDao;

    @Autowired
    private OrderItemDao orderItemDao;

    @Autowired
    private SkuDao skuDao;

    @Autowired
    private UserDao userDao;

    @Autowired
    private InvitationDao invitationDao;

    @Autowired
    private ProjectDao projectDao;

    @Autowired
    private OrderAssemble orderAssemble;

    @Autowired
    private ProjectSupportStore projectSupportStore;

    @Autowired
    private UserSupportProjectStore userSupportProjectStore;

    @Override
    @Transactional(propagation = Propagation.REQUIRED, noRollbackFor = Throwable.class, readOnly = false)
    public  Orders saveOrder(SecurityToken token, JsonResponse obj, OrderBean orderBean) {

        User user = userDao.getById(token.getOperatorUserId());
        if (orderBean == null) {
            JsonResponseHelper.addError(obj, CoreConstants.ORDER_NOT_IS_NULL);
            return null;
        } else if(user == null || user.getUserId() == 0){
            JsonResponseHelper.addError(obj, CoreConstants.USER_NOT_EXIST);
            return null;
        } else {
            Orders orders = new Orders();
            orders.setAddress(orderBean.getAddress());
            orders.setCity(orderBean.getCity());
            orders.setName(orderBean.getName());
            orders.setProvince(orderBean.getProvince());
            /*orders*/
            orders.setUserId(token.getOperatorUserId());
            orders.setSerialNumber(System.currentTimeMillis()
                    + ToolsImpl.getRandomString(2)
                    + token.getOperatorUserId());
            orders.setStatus(CoreConstants.ORDER_NOT_PAID);
            orders.setUseComments(orderBean.getRemarks());
            orders.setPhoneNumber(orderBean.getPhoneNumber());
            orderDao.save(orders, token);
            if (!ToolsImpl.isEmpty(orderBean.getOrderitems()) && orders.getOrderId() != 0) {
                for (OrderItemBean bean : orderBean.getOrderitems()) {
                    OrderItem item = new OrderItem();
                    Skus skus = skuDao.getBySkuId(bean.getSkuId());
                    if (skus == null || skus.getSkusId() == 0) {
                        JsonResponseHelper.addError(obj, CoreConstants.SKU_INVAIL);
                    }else{
                        item.setOrderId(orders.getOrderId());
                        item.setSkuId(bean.getSkuId());
                        item.setUnits(bean.getUnits());
                        orders.getOrderItemSet().add(item);
                        item.setSkus(skus);
                        orderItemDao.save(item, token);
                    }
                }
            }
            return orders;
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, noRollbackFor = Throwable.class, readOnly = true)
    public List<OrdersResp> getOrders(SecurityToken token, JsonResponse obj) {
        List<OrdersResp> ordersRespList = new ArrayList<OrdersResp>();
        User user = userDao.getById(token.getOperatorUserId());
        if (user == null || user.getUserId() == 0) {
            JsonResponseHelper.addError(obj, CoreConstants.USER_NOT_EXIST);
        } else {
            List<Orders> orders = orderDao.getById(token.getOperatorUserId());
            for(Orders order:orders) {
                OrdersResp ordersResp = orderAssemble.assembleOrder(order);
                ordersRespList.add(ordersResp);
            }

        }
        return ordersRespList;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, noRollbackFor = Throwable.class, readOnly = true)
    public List<OrdersResp> getNotPaidOrder(JsonResponse obj, SecurityToken token) {
        List<Orders> ordersList = orderDao.getgetNotPaidOrderByUserId(token.getOperatorUserId());
        if (!ToolsImpl.isEmpty(ordersList)) {
            List<OrdersResp> ordersRespList = orderAssemble.assembleOrderList(ordersList);
            return ordersRespList;
        }
        return new ArrayList<OrdersResp>();

    }
    @Override
    @Transactional(propagation = Propagation.REQUIRED, noRollbackFor = Throwable.class, readOnly = false)
    public void payActivity(SecurityToken token, JsonResponse obj,long orderId) {
        User user = userDao.getById(token.getOperatorUserId());
        if(user == null || user.getUserId() == 0){
            JsonResponseHelper.addError(obj, CoreConstants.SYSTEM_ERROR);
        }else if(user.getActivityStatus()!=null && user.getActivityStatus()!=0 && user.getActivityStatus() == 10){
            JsonResponseHelper.addError(obj, CoreConstants.USER_ACTIVITY_GET_ALREADY);
        }else{
            Long numberInvitee = invitationDao.getInviteeIdCount(token.getOperatorUserId());
            if(numberInvitee == null ||numberInvitee <2){
                JsonResponseHelper.addError(obj, CoreConstants.INVITEE_NOT_ENOUGH);
            }else{
                Orders orders = orderDao.getByOrderId(orderId);
                if(orders == null || orders.getOrderId() == 0){
                    JsonResponseHelper.addError(obj, CoreConstants.ORDER_INVIAL);
                }else{
                    if(orders.getStatus() == CoreConstants.ORDER_PAID){
                        JsonResponseHelper.addError(obj, CoreConstants.ORDER_PAID_ALREADY);
                    }else{
                        orders.setStatus(CoreConstants.ORDER_PAID);
                        orderDao.update(orders,token);
                        user.setActivityStatus(CoreConstants.USER_ACTIVITY_GET);
                        userDao.update(user,token);
                    }
                }

            }
        }

    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, noRollbackFor = Throwable.class, readOnly = false)
    public List<Orders> searchOrdersByProjectId(SecurityToken token, long projectId, SearchOrder searchOrder, JsonResponse obj) {

        List<Orders> ordersList = orderDao.searchOrdersByProjectId(searchOrder.getIndex(), searchOrder.getSize(), projectId);
        return ordersList;
    }




    @Transactional(propagation = Propagation.REQUIRED, noRollbackFor = Throwable.class, readOnly = true)
    public Orders getByOrderId(long orderId) {

        return orderDao.getByOrderId(orderId);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, noRollbackFor = Throwable.class, readOnly = false)
    public void payOrder(SecurityToken token, JsonResponse obj, PayOrder payOrder) {
        Orders order = orderDao.getByOrderId(payOrder.getOrderId());
        if(order == null) {
            JsonResponseHelper.addError(obj, CoreConstants.ORDER_INVIAL);
        } else if (order.getStatus() == OrderStatus.ORDER_PAID) {
            JsonResponseHelper.addError(obj, CoreConstants.ORDER_PAID_ALREADY);
        } else {

            SupportUser supportUser = new SupportUser();
            supportUser.setDate(new Date());
            supportUser.setNickName(payOrder.getNickName());
            supportUser.setNum(payOrder.getNumber());
            supportUser.setPrice(payOrder.getPrice());
            supportUser.setHeadIcon(payOrder.getHeadIcon());
            ProjectSupport projectSupport = projectSupportStore.searchProjectSupport(payOrder.getProjectId());
            if(projectSupport == null) {
                projectSupport = new ProjectSupport();
                projectSupport.setPeopleNum(0);
                projectSupport.setGetFinancing(0.0);
                projectSupport.setProjectId(payOrder.getProjectId());
            }
            double getFinancing = projectSupport.getGetFinancing();
            getFinancing += payOrder.getPrice();
            projectSupport.setGetFinancing(getFinancing);
            projectSupport.getSupportUserList().add(supportUser);
            projectSupport.setPeopleNum(projectSupport.getPeopleNum()+1);
            order.setStatus(OrderStatus.ORDER_PAID);
            orderDao.update(order,token);
            projectSupportStore.save(projectSupport);

            UserSupportProject userSupportProject =userSupportProjectStore.searchSupportedProject(token.getOperatorUserId());
            if (userSupportProject == null) {
                userSupportProject = new UserSupportProject();
                userSupportProject.setUserId(token.getOperatorUserId());
            }
            List<Long> supportedProjectIdList = userSupportProject.getSupportedProjectIdList();
            boolean supported = false;
            for (Long id : supportedProjectIdList) {
                if (id == payOrder.getProjectId()) {
                    supported = true;
                    return ;
                }
            }
            if (!supported) {
                supportedProjectIdList.add(payOrder.getProjectId());
                userSupportProjectStore.save(userSupportProject);
            }
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, noRollbackFor = Throwable.class, readOnly = false)
    public void saveLogisticOrder(SecurityToken token, Logististic logistic, JsonResponse obj) {
        Orders order = orderDao.getByOrderId(logistic.getOrderId());

        if(order!=null && order.getOrderId()!=0){
            order.setExpressNumber(logistic.getExpressNumber());
            order.setExpressCompany(logistic.getExpressCompany());
            orderDao.update(order,token);
        }else {
            JsonResponseHelper.addError(obj, CoreConstants.ORDER_NOT_EXITS);
        }

    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, noRollbackFor = Throwable.class, readOnly = false)
    public List<OrdersResp> getByUidAndPid(SearchProjects searchProjects, Long userId, Long projectId) {
        List<Orders> ordersList = orderDao.getByUidAndPid(searchProjects.getIndex(), searchProjects.getSize(),userId, projectId);
        List<OrdersResp> ordersRespList = orderAssemble.assembleOrderList(ordersList);
        return ordersRespList;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, noRollbackFor = Throwable.class, readOnly = false)
    public void deleteOrder(SecurityToken token, JsonResponse obj, long orderId) {
        Orders orders = orderDao.getByOrderId(orderId);
        if (orders == null) {
            JsonResponseHelper.addError(obj, CoreConstants.ORDER_NOT_EXITS);
        } else {
            List<OrderItem> orderItemList = orderItemDao.searchOrderItemByOrderId(orderId);
            if (ToolsImpl.isEmpty(orderItemList)) {
                JsonResponseHelper.addError(obj, CoreConstants.ORDER_SKU_ERROR);
            } else {
                for (OrderItem orderItem : orderItemList) {
                    orderItemDao.delete(orderItem);
                }
                orderDao.delete(orders);
            }
        }
    }
    @Override
    @Transactional(propagation = Propagation.REQUIRED, noRollbackFor = Throwable.class, readOnly = false)
    public void confirmReceipt(SecurityToken token, JsonResponse obj, ConfirmReceipt confirmReceipt, long orderId) {
        User user = userDao.getById(token.getOperatorUserId());
        if (user == null || user.getUserId() == 0) {
            JsonResponseHelper.addError(obj, CoreConstants.SYSTEM_ERROR);
            return;
        }  else if (!ToolsImpl.isValidPassword(confirmReceipt.getPassword(),user.getPassword())) {
            JsonResponseHelper.addError(obj, CoreConstants.PASSWORD_ERROR);
            return;
        } else {
            Orders orders = orderDao.getByOrderId(orderId);
            if (orders == null || orders.getOrderId() == 0) {
                JsonResponseHelper.addError(obj, CoreConstants.ORDER_INVIAL);
            }  else if (!(orders.getStatus() == OrderStatus.ORDER_PAID)) {
                JsonResponseHelper.addError(obj, CoreConstants.ORDER_CANT_CONFIRM_RECEIVE);
                return;
            } else {
                if (orders.getStatus() == CoreConstants.ORDER_RECEIVED) {
                    JsonResponseHelper.addError(obj, CoreConstants.ORDER_RECEIVED_ALREADY);
                } else {
                    orders.setStatus(CoreConstants.ORDER_RECEIVED);
                }
            }
        }
    }
    @Override
    @Scheduled(cron = "0 0 12 * * ?")/*0/3 * * * * ?   0 0 12 * * ?*/
    @Transactional(propagation = Propagation.REQUIRED, noRollbackFor = Throwable.class, readOnly = false)
    public void autoConfirmReceipt() {
        Date date = new Date();
        List<Projects> projectsList = projectDao.getFinishedProject();
        for (Projects pro : projectsList) {
            long time = date.getTime()-pro.getDispatchTime().getTime();
            if (time >= 15*24*60*60*1000){
                List<Orders> ordersList = orderDao.searchOrdersByProjectId(pro.getProjectId());
                for (Orders or : ordersList) {
                    or.setStatus(OrderStatus.ORDER_RECEIVED);
                    SecurityToken token = new SecurityToken(or.getUserId());
                    token.setChannel(ServiceChannel.getUserTypeCode(or.getProcessChannel()));
                    token.setOperatorUserId(or.getUserId());
                    token.setProcessName(or.getProcessName());
                    token.setRequestTime(or.getProcessTimeStamp());
                    token.setSessionId(or.getSessionId());
                    orderDao.update(or, token);
                }
            }
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, noRollbackFor = Throwable.class, readOnly = false)
    public void sellerSetconfirmReceipt(SecurityToken token, JsonResponse obj, String serialNumber) {
        User user = userDao.getById(token.getOperatorUserId());
        if (user == null) {
            JsonResponseHelper.addError(obj, CoreConstants.USER_NOT_EXIST);
        } else if (user.getType() != UserType.BUSINESS) {
            JsonResponseHelper.addError(obj, CoreConstants.USER_NOT_BUSINESS);
        } else {
            Orders order = orderDao.getBySerialNumber(serialNumber);
            if (order == null) {
                JsonResponseHelper.addError(obj, CoreConstants.ORDER_NOT_EXITS);
            } else {
                Projects pro = projectDao.getByOrderId(order.getOrderId());
                if (pro.getType() == ProjectType.TYPE_NEED_RECEIVE_GOOD) {
                    JsonResponseHelper.addError(obj, CoreConstants.PROJECT_NEDD_RECEIVE_GOOD);
                }
                order.setStatus(OrderStatus.ORDER_RECEIVED);
                orderDao.update(order, token);
            }
        }
    }

}
